
#include <stdio.h>
#include <Windows.h>
#include <mmsystem.h>
#include <d3dx9.h>

#include "SkinMesh.h"

LPDIRECT3D9					g_pD3D			=NULL;
LPDIRECT3DDEVICE9			g_pd3dDevice	=NULL; 

CSkinMesh*					g_pRole			=NULL;


HRESULT InitD3D(HWND hWnd)
{
	if(NULL==(g_pD3D=Direct3DCreate9(D3D_SDK_VERSION)))
		return E_FAIL;
	
	D3DPRESENT_PARAMETERS d3dpp;
	ZeroMemory(&d3dpp,sizeof(d3dpp));
	d3dpp.Windowed=TRUE;
	d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferFormat=D3DFMT_UNKNOWN;
	d3dpp.EnableAutoDepthStencil=TRUE;
	d3dpp.AutoDepthStencilFormat=D3DFMT_D16;
	
	if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,
		D3DCREATE_SOFTWARE_VERTEXPROCESSING,
		&d3dpp,&g_pd3dDevice)))
	{
		return E_FAIL;
	}
	
	g_pd3dDevice->SetRenderState( D3DRS_LIGHTING,         FALSE );
    g_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE,     TRUE );
    g_pd3dDevice->SetRenderState( D3DRS_ZENABLE,          TRUE );
    g_pd3dDevice->SetRenderState( D3DRS_CULLMODE,         D3DCULL_CCW );
    g_pd3dDevice->SetRenderState( D3DRS_AMBIENT,          0x33333333 );
    g_pd3dDevice->SetRenderState( D3DRS_NORMALIZENORMALS, TRUE );
    g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
    g_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );

	return S_OK;
}


VOID Cleanup()
{
		
	if(g_pd3dDevice!=NULL)
		g_pd3dDevice->Release();
	
	if(g_pD3D!=NULL)
		g_pD3D->Release();
}

void SetupView()
{
	D3DXVECTOR3 vEyePt( 0.0f, 0.0f , -800.0f);
	D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
	D3DXVECTOR3 vUpVec( 0.0f, 0.0f, 1.0f );
	D3DXMATRIXA16 matView;
	D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
	g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
}

void SetupProjection()
{
	D3DXMATRIXA16 matProj;
	D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 2000.0f );
	g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}

VOID Render()
{
	g_pd3dDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(160,160,160),1.0f,0);
	
	if(SUCCEEDED(g_pd3dDevice->BeginScene()))
	{
		g_pRole->Render();
		g_pd3dDevice->EndScene();
	}

	g_pd3dDevice->Present(NULL,NULL,NULL,NULL);
}

LRESULT WINAPI MsgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
	switch(msg)
	{
	case WM_DESTROY:
		Cleanup();
		PostQuitMessage(0);
		return 0;
	}
	
	return DefWindowProc(hWnd,msg,wParam,lParam);
}

INT WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR,INT)
{
	WNDCLASSEX wc={sizeof(WNDCLASSEX),CS_CLASSDC,MsgProc,0L,0L,
		GetModuleHandle(NULL),NULL, NULL, NULL, NULL,
		"My D3D",NULL};
	RegisterClassEx(&wc);
	
	HWND hWnd=CreateWindow("My D3D","http://kuga.51.net",
		WS_OVERLAPPEDWINDOW,100,60,600,480,
		GetDesktopWindow(),NULL,wc.hInstance,NULL);
	
	if(SUCCEEDED(InitD3D(hWnd)))
	{
		SetupView();
		SetupProjection();
		
		g_pRole=new CSkinMesh(g_pd3dDevice);
		g_pRole->LoadFromXFile("tiny.x");
		
		ShowWindow(hWnd,SW_SHOWDEFAULT);
		UpdateWindow(hWnd);
		
		MSG msg;
		ZeroMemory(&msg,sizeof(msg));
		
		while(msg.message!=WM_QUIT)
		{
			if(PeekMessage(&msg,NULL,0U,0U,PM_REMOVE))
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
			else Render();
		}
		
		delete g_pRole;
	}
	
	UnregisterClass("My D3D",wc.hInstance);
	return 0;
}